package csel.view.status;

import csel.controller.bindings.StringActionCommands;
import csel.model.Observer;
import csel.model.entity.Character;
import csel.model.skills.*;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.List;

import javax.swing.*;

public class SkillMenu extends JPanel implements Observer<Object>
{
	
	private static final long serialVersionUID = 1L;
	
	private Character myCharacter;
	private ActionListener myListener;
	private final SkillMenuManager myManager;
	
	private JScrollPane myScrollPane;
	private JPanel skillsPanel;
	
	private List<RangedActiveSkill> rangedSkillSet;
	private List<NonRangedActiveSkill> nonrangedSkillSet;
	private List<PassiveSkill> passiveSkillSet;
	
	private LinkedList<JLabel> nameSet = new LinkedList<JLabel>();
	//private LinkedList<JLabel> descSet = new LinkedList<JLabel>();
	private LinkedList<JLabel> levelSet = new LinkedList<JLabel>();
	private LinkedList<JButton> useSelfButtonSet = new LinkedList<JButton>();
	private LinkedList<JButton> useOtherButtonSet = new LinkedList<JButton>();
	private LinkedList<JButton> upButtonSet = new LinkedList<JButton>();
	
	private Skill lastSelected = null;
	
	public static SkillMenu initialize(Character myCharacter, ActionListener myListener)
	{
		SkillMenu theSkillMenu = new SkillMenu(myCharacter, myListener);
		myCharacter.addObserver(theSkillMenu);
		return theSkillMenu;
	}
	
	private SkillMenu(Character myCharacter, ActionListener myListener)
	{
		this.myCharacter = myCharacter;
		this.myListener = myListener;
		myManager = new SkillMenuManager();
		
		skillsPanel = new JPanel();
		
		setLayout(new GridBagLayout());
		skillsPanel.setLayout(new GridBagLayout());
		//skillsPanel.setPreferredSize(new Dimension(375,125));
		buildSkillsPanel();
		
		setPreferredSize(new Dimension(375,125));
		setOpaque(false);
	}
	
	private void buildSkillsPanel()
	{
		GridBagConstraints c = new GridBagConstraints();
		
		nameSet = new LinkedList<JLabel>();
		levelSet = new LinkedList<JLabel>();
		useSelfButtonSet = new LinkedList<JButton>();
		useOtherButtonSet = new LinkedList<JButton>();
		upButtonSet = new LinkedList<JButton>();
		
		SkillsProxy myProxy = myCharacter.getMySkills();
		rangedSkillSet = myProxy.getRangedSkills();
		nonrangedSkillSet = myProxy.getNonRangedSkills();
		passiveSkillSet = myProxy.getPassiveSkills();
		
		int currentRow = 0;
		
		int rangedSize = rangedSkillSet.size();
		int nonrangedSize = nonrangedSkillSet.size();
		int passiveSize = passiveSkillSet.size();
		
		//TODO: change this based on updated skill thingie
		for (PassiveSkill s: passiveSkillSet)
		{
			nameSet.add(textLabel(s.getName(),Color.BLACK,12));
			levelSet.add(levelLabel(s.getPointsAllocated()));
			JButton temp = upgradeButton(s);
			temp.setFocusable(false);
			upButtonSet.add(temp);
		}
		
		for (NonRangedActiveSkill s: nonrangedSkillSet)
		{
			nameSet.add(textLabel(s.getName(),Color.BLACK,12));
			levelSet.add(levelLabel(s.getPointsAllocated()));
			JButton temp = upgradeButton(s);
			temp.setFocusable(false);
			upButtonSet.add(temp);
			temp = useSelfButton(s);
			temp.setFocusable(false);
			useSelfButtonSet.add(temp);
			temp = useOtherButton(s);
			temp.setFocusable(false);
			useOtherButtonSet.add(temp);
		}
		
		for (RangedActiveSkill s: rangedSkillSet)
		{
			nameSet.add(textLabel(s.getName(),Color.BLACK,12));
			levelSet.add(levelLabel(s.getPointsAllocated()));
			JButton temp = upgradeButton(s);
			temp.setFocusable(false);
			upButtonSet.add(temp);
			temp = useOtherButton(s);
			temp.setFocusable(false);
			useOtherButtonSet.add(temp);
			
		}
		
		int i = passiveSize;
		for (int a = 0; a < i; ++a)
		{
			c.gridwidth = 1;
			c.gridy = ++currentRow;
			c.ipady = 5;
			c.gridx = 0;
			skillsPanel.add(nameSet.get(a),c);
			c.gridx = 1;
			c.gridy = currentRow;
			skillsPanel.add(levelSet.get(a),c);
			c.gridx = 0;
			c.gridy = ++currentRow;
			skillsPanel.add(upButtonSet.get(a),c);
		}

		i = nonrangedSize;
		for (int a = 0; a < i; ++a)
		{
			c.gridwidth = 1;
			c.gridy = ++currentRow;
			c.ipady = 5;
			c.gridx = 0;
			skillsPanel.add(nameSet.get(a+passiveSize),c);
			c.gridx = 1;
			c.gridy = currentRow;
			skillsPanel.add(levelSet.get(a+passiveSize),c);
			c.gridx = 0;
			c.gridy = ++currentRow;
			skillsPanel.add(upButtonSet.get(a+passiveSize),c);
			c.gridx = 1;
			skillsPanel.add(useSelfButtonSet.get(a),c);
			c.gridx = 2;
			skillsPanel.add(useOtherButtonSet.get(a),c);
		}
		
		i = rangedSize;
		for (int a = 0; a < i; ++a)
		{
			c.gridwidth = 1;
			c.gridy = ++currentRow;
			c.ipady = 5;
			c.gridx = 0;
			skillsPanel.add(nameSet.get(a+passiveSize+nonrangedSize),c);
			c.gridx = 1;
			c.gridy = currentRow;
			skillsPanel.add(levelSet.get(a+passiveSize+nonrangedSize),c);
			c.gridx = 0;
			c.gridy = ++currentRow;
			skillsPanel.add(upButtonSet.get(a+passiveSize+nonrangedSize),c);
			c.gridx = 1;
			skillsPanel.add(useOtherButtonSet.get(a),c);
		}
		
		skillsPanel.setOpaque(false);
		skillsPanel.validate();
		skillsPanel.repaint();
		
		myScrollPane = new JScrollPane(skillsPanel,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		myScrollPane.setPreferredSize(new Dimension(375,125));
		myScrollPane.setOpaque(false);
		add(myScrollPane);

		setPreferredSize(new Dimension(200,50));
	}
	
	public void mupdate(Object o, Object param)
	{
		if (o.equals(myCharacter))
		{
			removeAll();
			buildSkillsPanel();
			validate();
			repaint();
			
		}
	}
	
	public void setCharacter(Character c)
	{
		myCharacter = c;
		myCharacter.addObserver(this);
		removeAll();
		buildSkillsPanel();
		revalidate();
	}
	
	public Skill getSelectedSkill()
	{
		return lastSelected;
	}

	private JButton upgradeButton(Skill mySkill)
	{
		JButton myButton = new JButton("Upgrade");
		myButton.setActionCommand(StringActionCommands.BM_SKILLS_UPGRADE);
		myButton.putClientProperty("contents",mySkill);
		myButton.addActionListener(myManager);
		return myButton;
	}
	
	private JButton useSelfButton(Skill mySkill)
	{
		JButton myButton = new JButton("Use (Self)");
		myButton.setActionCommand(StringActionCommands.BM_SKILLS_USESELF);
		myButton.putClientProperty("contents",mySkill);
		myButton.addActionListener(myManager);
		return myButton;
	}
	
	private JButton useOtherButton(Skill mySkill)
	{
		JButton myButton = new JButton("Use (Other)");
		myButton.setActionCommand(StringActionCommands.BM_SKILLS_USEOTHER);
		myButton.putClientProperty("contents",mySkill);
		myButton.addActionListener(myManager);
		return myButton;
	}
	
	private JLabel levelLabel(int i)
	{
		return new JLabel("Level: "+i);
	}
	
	private JLabel textLabel(String s, Color c, int size)
	{
		JLabel myLabel = new JLabel(s);
		myLabel.setFont(new Font("Serif", Font.PLAIN, size));
		myLabel.setForeground(c);
		return myLabel;

	}
	
	//only responsible for enabling/disabling the use and equip buttons based on the type
    //of item that is selected.
    private class SkillMenuManager implements ActionListener
    {
            public void actionPerformed(ActionEvent e)
            {
            	JButton theButton = ((JButton) e.getSource());
                lastSelected = (Skill) theButton.getClientProperty("contents");
                myListener.actionPerformed(e);
            }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException
    {
            throw new java.io.NotSerializableException("SkillMenu should not be serialized.");
    }
    
    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException
    {
            throw new java.io.NotSerializableException("SkillMenu should not be serialized.");
    }

}
